AWS SAMでLambdaオーソライザーを「適用するAPI」と「適用しないAPI」を作ってみた
AWS SAMでLambdaオーソライザーを適用したAPIと適用しないAPIを作ってみました。
CognitoやAuth0を使って、API GatewayのLambdaオーソライザーで「OK・NG」を判断することは多いと思います。 このとき、一部のAPIを公開したくなったので、試してみました。
OpenAPIを使った場合は、下記をご覧ください。
おすすめの方
- AWS SAMでLambdaオーソライザーを作りたい方
- AWS SAMで一部のAPI(Lambda)にLambdaオーソライザーを適用したくない方
サーバーレスアプリを作成する
sam init
sam init \ --runtime python3.8 \ --name Lambda-Authorizer-Sample \ --app-template hello-world \ --package-type Zip
SAMテンプレート
Lambda自体は3つ作成します。
- Lambdaオーソライザー
GET /hello
用(Authorizerあり)GET /hello2
用(Authorizerなし)
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Lambda-Authorizer-Sample Resources: MyApi: Type: AWS::Serverless::Api Properties: StageName: dev Auth: DefaultAuthorizer: MyLambdaAuthorizer Authorizers: MyLambdaAuthorizer: FunctionArn: !GetAtt AuthorizerFunction.Arn Identity: ReauthorizeEvery: 0 # Lambda Authorizer AuthorizerFunction: Type: AWS::Serverless::Function Properties: CodeUri: hello_world/ Handler: authorizer.lambda_handler Runtime: python3.8 Timeout: 5 AuthorizerFunctionLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/lambda/${AuthorizerFunction} # API: GET /hello (Authorizerあり) HelloWorldFunction: Type: AWS::Serverless::Function Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.8 Timeout: 5 Events: HelloWorld: Type: Api Properties: Path: /hello Method: get RestApiId: !Ref MyApi HelloWorldFunctionLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/lambda/${HelloWorldFunction} # API: GET /hello2 (Authorizerなし) HelloWorld2Function: Type: AWS::Serverless::Function Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.8 Timeout: 5 Events: HelloWorld: Type: Api Properties: Path: /hello2 Method: get RestApiId: !Ref MyApi Auth: Authorizer: NONE HelloWorld2FunctionLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/lambda/${HelloWorld2Function} Outputs: HelloWorldApi: Value: !Sub "https://${MyApi}.execute-api.${AWS::Region}.amazonaws.com/dev/hello"
Lambdaコード
Authorizer
authorization
がabc
ならOKとしています。
def lambda_handler(event, context): token = event['authorizationToken'] effect = 'Deny' if token == 'abc': effect = 'Allow' return { 'principalId': '*', 'policyDocument': { 'Version': '2012-10-17', 'Statement': [ { 'Action': 'execute-api:Invoke', 'Effect': effect, 'Resource': event['methodArn'] } ] } }
GET /hello
用
GET /hello2
と共通です。
import json def lambda_handler(event, context): return { 'statusCode': 200, 'body': json.dumps({ 'message': 'hello world', }), }
デプロイ
sam build sam package \ --output-template-file packaged.yaml \ --s3-bucket cm-fujii.genki-deploy sam deploy \ --template-file packaged.yaml \ --stack-name Lambda-Authorizer-Sample-Stack \ --s3-bucket cm-fujii.genki-deploy \ --capabilities CAPABILITY_NAMED_IAM \ --no-fail-on-empty-changeset
動作確認
APIエンドポイントを取得する
aws cloudformation describe-stacks \ --stack-name Lambda-Authorizer-Sample-Stack \ --query 'Stacks[].Outputs'
GET /hello
Authorizationあり(OK)
curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello \ --header 'authorization: abc' {"message": "hello world"}
Authorizationあり(NG)
curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello \ --header 'authorization: xxx' {"Message":"User is not authorized to access this resource with an explicit deny"}
Authorizationなし(NG)
curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello {"message":"Unauthorized"}
GET /hello2
Authorizationなし(OK)
curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello2 {"message": "hello world"}